package com.pig4cloud.pig.ads.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.pig4cloud.pig.admin.api.entity.SysUser;
import com.pig4cloud.pig.admin.api.feign.RemoteUserService;
import com.pig4cloud.pig.ads.clickhouse3399.mapper.AdAudienceMapper;
import com.pig4cloud.pig.ads.gdt.service.GdtAccesstokenService;
import com.pig4cloud.pig.ads.pig.mapper.*;
import com.pig4cloud.pig.ads.pig.mapper.gdt.GdtAdvFundsMapper;
import com.pig4cloud.pig.ads.pig.mapper.gdt.GdtAdvertiserMapper;
import com.pig4cloud.pig.ads.service.AdAccountWarningResultService;
import com.pig4cloud.pig.ads.service.TtAccesstokenService;
import com.pig4cloud.pig.ads.service.mail.MessageService;
import com.pig4cloud.pig.ads.utils.DateUtils;
import com.pig4cloud.pig.ads.utils.OEHttpUtils;
import com.pig4cloud.pig.api.dto.AdTtTransferDto;
import com.pig4cloud.pig.api.entity.*;
import com.pig4cloud.pig.api.gdt.entity.GdtAdvFunds;
import com.pig4cloud.pig.api.gdt.vo.GdtAdvFundsVO;
import com.pig4cloud.pig.api.util.JsonUtil;
import com.pig4cloud.pig.api.util.MapUtils;
import com.pig4cloud.pig.api.vo.AdAccountWarnVo;
import com.pig4cloud.pig.api.vo.AdTtTransferVo;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.constant.enums.PlatformTypeEnum;
import com.pig4cloud.pig.common.core.util.R;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description 账户提醒结果service
 * @Author chengang
 * @Date 2021/7/13
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class AdAccountWarningResultServiceImpl extends ServiceImpl<AdAccountWarningResultMapper, AdAccountWarningResult> implements AdAccountWarningResultService {

	private final AdAccountWarningSettingMapper adAccountWarningSettingMapper;

	private final AdvertiserMapper advertiserMapper;

	private final GdtAdvertiserMapper gdtAdvertiserMapper;

	private final GdtAdvFundsMapper gdtAdvFundsMapper;

	private final AdAudienceMapper adAudienceMapper;

	private final AdAccountMapper adAccountMapper;

	private final RemoteUserService remoteUserService;

	private final MessageService messageService;

	private final TtAccesstokenService ttAccesstokenService;

	private final GdtAccesstokenService gdtAccesstokenService;

	private final AdTtTransferMapper adTtTransferMapper;

	private final AdAgentTransferMapper adAgentTransferMapper;

	@Value("${warning.account.email.subject:}")
	private String subject;

	// 广点通公共域名
	@Value(value = "${gdt_url}")
	private String gdtUrl;


	@Override
	public List<Advertising> getTtAdAccountListByIds(List<String> ids) {
		if (CollectionUtils.isEmpty(ids)) {
			return Lists.newArrayList();
		}
		return advertiserMapper.selectList(Wrappers.<Advertising>lambdaQuery()
				.eq(Advertising::getDeleted,0)
				.in(Advertising::getAdvertiserId, ids));
	}

	@Override
	public List<GdtAdvFunds> getGdtAdAccountListByIds(List<String> ids) {
		if (CollectionUtils.isEmpty(ids)) {
			return Lists.newArrayList();
		}
		List<GdtAdvFunds> gdtAdvFundsList = gdtAdvFundsMapper.selectList(Wrappers.<GdtAdvFunds>lambdaQuery()
				.in(GdtAdvFunds::getAccountId, ids));
		if (CollectionUtils.isNotEmpty(gdtAdvFundsList)) {
			gdtAdvFundsList.forEach(advFund -> {
				if (StringUtils.isNotBlank(advFund.getFunds())) {
					List<GdtAdvFundsVO> fundList = JsonUtil.fromJsonArray(advFund.getFunds(), GdtAdvFundsVO.class);
					//获取总余额
					BigDecimal totalBalance = fundList.stream().map(item -> item.getBalance()).reduce(BigDecimal.ZERO, BigDecimal::add);
					advFund.setTotalBalance(totalBalance);
					advFund.setFundList(fundList);
				}
			});
		}
		return gdtAdvFundsList;
	}

	@Override
	public List<AdAccountWarnVo> getNoCostCount(List<String> ids) {
		if (CollectionUtils.isEmpty(ids)) {
			return Lists.newArrayList();
		}
		return adAudienceMapper.selectNoCostCount(ids);
	}

	/**
	 * 获取不活跃账户集合
	 *
	 * @return
	 */
	@Override
	//@Scheduled(initialDelay = 5000, fixedDelay = 15000)
	public R getNoActiveAccountList(Integer userId) {
		//有设定条件才拉取
		AdAccountWarningSetting setting = this.getSetting();
		//不活跃：指定周期未有消耗，并且总余额不为0
		if (setting != null) {
			List<AdAccountWarningResult> entityList = Lists.newArrayList();
			List<AdAccountWarningResult> activeAccountList = Lists.newArrayList();
			List<String> allIds = Lists.newArrayList();
			List<String> ttActiveIds = this.getTtAdList();
			List<String> gdtActiveIds = this.getGdtAdList();
			allIds.addAll(ttActiveIds);
			allIds.addAll(gdtActiveIds);
			//查询余额大于0，活跃的广告账户集合
			List<AdAccountWarnVo> adAccountWarnVoList = adAudienceMapper.selectWarnAccount(allIds);
			if (CollectionUtils.isNotEmpty(adAccountWarnVoList)) {
				//按类型分组
				adAccountWarnVoList.forEach(adAccountWarnVo -> {
					AdAccountWarningResult tmp = new AdAccountWarningResult();
					tmp.setMediaType(adAccountWarnVo.getMediaType());
					tmp.setAdvertiserId(adAccountWarnVo.getAdAccount());
					//计算是否活跃
					Date maxActiveDate = DateUtils.stringToDate(adAccountWarnVo.getMaxDay(), DateUtils.YYYYMMDD);
					Date tmpDate = DateUtils.addDays(maxActiveDate, setting.getDays());
					// 当前系统时间 >= MAX活跃时间 + 设定的天数   --可以在SQL中过滤
					if (!new Date().before(tmpDate)) {
						tmp.setActive(2);
					} else {
						//预留活跃账户类型--防止后期要查活跃的账户列表
						tmp.setActive(1);
					}
					tmp.setActiveDate(maxActiveDate);
					//定时获取不到userId,默认传 -1
					//Integer userId = SecurityUtils.getUser().getId();
					tmp.setCreateId(Long.valueOf(userId));
					tmp.setUpdateId(Long.valueOf(userId));
					activeAccountList.add(tmp);
				});
			}

			//头条-获取所有总余额大于0的广告账户 且 不活跃的账户
			List<AdAccountWarningResult> ttActiveAccountList = this.dealNoActiveAccount(userId, ttActiveIds, adAccountWarnVoList, Integer.parseInt(PlatformTypeEnum.TT.getValue()));
			//广点通-获取所有总余额大于0的广告账户 且 不活跃的账户
			List<AdAccountWarningResult> gdtActiveAccountList = this.dealNoActiveAccount(userId, gdtActiveIds, adAccountWarnVoList, Integer.parseInt(PlatformTypeEnum.GDT.getValue()));
			//insert ad_account_warning_result
			if (CollectionUtils.isNotEmpty(activeAccountList)) {
				entityList.addAll(activeAccountList);
			}
			if (CollectionUtils.isNotEmpty(ttActiveAccountList)) {
				entityList.addAll(ttActiveAccountList);
			}
			if (CollectionUtils.isNotEmpty(gdtActiveAccountList)) {
				entityList.addAll(gdtActiveAccountList);
			}
			if (CollectionUtils.isNotEmpty(entityList)) {
				//不用按 media_type、advertiser_id更新，直接先删除后插入
				this.baseMapper.deleteAll();
				boolean result = this.saveBatch(entityList);
				if (!result) {
					return R.failed("保存不活跃用户失败");
				}
			} else {
				log.info("不活跃账户设定的规则没有数据");
			}
		} else {
			log.info("不活跃账户规则还未设定,请先设定。");
		}
		return R.ok();
	}

	@Override
	public R noActiveAccountSendMail() {
		//有设定条件才发送邮件
		AdAccountWarningSetting setting = this.getSetting();
		if (setting != null) {
			//拉取不活跃账户时已计算总余额大于0，暂不考虑到发送邮件之间的时间差
			Date now = new Date();
			//获取当天yyyy-MM-dd格式的时间
			String currentDate = DateUtils.dateToString(now, DateUtils.YYYY_MM_DD);
			Date yyyyMMddNow = DateUtils.stringToDate(currentDate, DateUtils.YYYY_MM_DD);
			//判断当天的邮件是否已发送(ps:每次重新设定规则时将清空每日发送邮件日期 is_send = 1(没有发送))
			if (setting.getIsSend() == 2 && yyyyMMddNow.compareTo(setting.getSendDate()) == 0) {
				return R.ok(null, "当天邮件已经发送");
			}
			Date settingDate = DateUtils.stringToDate(currentDate + " " + setting.getTimes() + ":00", DateUtils.YYYY_MM_DD_HH_MM_SS);
			// 系统时间 >= 系统时间 + times
			if (now.compareTo(settingDate) >= 0) {
				//满足设定时间，获取不活跃账户列表
				List<AdAccountWarningResult> totalList = this.getNoActiveList();
				this.setNameAndAmount(totalList);
				if (CollectionUtils.isNotEmpty(totalList)) {
					//邮件发送
					//获取用户的邮箱并过滤空邮箱
					List<Integer> userIds = new ArrayList<>(Arrays.asList(setting.getUsers().split(","))).stream()
							.map(v -> Integer.parseInt(v)).collect(Collectors.toList());
					List<String> emailAddress = getEmailAddressList(userIds);
					String emailContent = getEmailContent(totalList);
					messageService.sendMail(subject, emailContent, emailAddress);

					//更新邮件发送日期为当天并设置is_send=2,满足当天已发送第二天再次发送一次的场景
					setting.setIsSend(2);
					setting.setSendDate(yyyyMMddNow);
					adAccountWarningSettingMapper.updateById(setting);
					return R.ok(null, "1.没收到邮件请查看收件人是否配置了邮箱 2.列表余额显示0表示统计时账户有钱,发送邮件是账户余额为0(下一次统计就会过滤)");
				}
			} else {
				return R.ok(null, "没到指定时间，不发送邮件");
			}
		} else {
			return R.ok(null, "不活跃账户规则还未设定");
		}
		return R.ok();
	}

	private List<String> getTtAdList() {
		List<String> ttActiveList = Lists.newArrayList();
		//头条-获取所有总余额大于0的广告账户
		List<Advertising> ttAdvertisingList = advertiserMapper.selectList(Wrappers.<Advertising>lambdaQuery()
				.gt(Advertising::getBalance, 0));
		if (CollectionUtils.isNotEmpty(ttAdvertisingList)) {
			ttActiveList = ttAdvertisingList.stream().map(Advertising::getAdvertiserId).collect(Collectors.toList());
		}
		return ttActiveList;
	}

	private List<String> getGdtAdList() {
		List<String> gdtActiveList = Lists.newArrayList();
		//腾讯-获取所有总余额大于0的广告账户
		//在json串中，需要解析。。。
		List<GdtAdvFunds> gdtAdvFundsList = gdtAdvFundsMapper.selectList(Wrappers.<GdtAdvFunds>lambdaQuery().apply("1=1"));
		if (CollectionUtils.isNotEmpty(gdtAdvFundsList)) {
			Map<String, GdtAdvFunds> gdtAdMap = gdtAdvFundsList.stream().collect(Collectors.toMap(GdtAdvFunds::getAccountId, Function.identity()));
			for (String key : gdtAdMap.keySet()) {
				GdtAdvFunds tmp = gdtAdMap.get(key);
				List<GdtAdvFundsVO> fundList = JsonUtil.fromJsonArray(tmp.getFunds(), GdtAdvFundsVO.class);
				//获取总余额
				BigDecimal totalBalance = fundList.stream().map(item -> item.getBalance()).reduce(BigDecimal.ZERO, BigDecimal::add);
				//计算总余额大于0的账户
				if (totalBalance.compareTo(BigDecimal.ZERO) == 1) {
					gdtActiveList.add(key);
				}
			}
		}
		return gdtActiveList;
	}

	private AdAccountWarningSetting getSetting() {
		return adAccountWarningSettingMapper.selectOne(Wrappers.<AdAccountWarningSetting>lambdaQuery()
				.eq(AdAccountWarningSetting::getIsDeleted, 0));
	}

	/**
	 * 获取全部不活跃账户集合
	 *
	 * @return
	 */
	@Override
	public List<AdAccountWarningResult> getNoActiveList() {
		LambdaQueryWrapper<AdAccountWarningResult> query = new LambdaQueryWrapper<>();
		query.and(wrapper -> wrapper.eq(AdAccountWarningResult::getIsDeleted, 0));
		query.and(wrapper -> wrapper.eq(AdAccountWarningResult::getActive, 2));
		query.orderByDesc(AdAccountWarningResult::getCreateTime);
		List<AdAccountWarningResult> list = this.getBaseMapper().selectList(query);
		return list;
	}

	@Override
	public BigDecimal setNameAndAmount(List<AdAccountWarningResult> list) {
		BigDecimal totalBalance = BigDecimal.ZERO;
		if (CollectionUtils.isNotEmpty(list)) {
			List<String> adIds = list.stream().map(AdAccountWarningResult::getAdvertiserId).filter(Objects::nonNull).collect(Collectors.toList());
			List<AdAccount> adAccountList = adAccountMapper.selectList(Wrappers.<AdAccount>lambdaQuery()
					.in(AdAccount::getAdvertiserId, adIds));
			// 设置余额
			Integer tt = Integer.parseInt(PlatformTypeEnum.TT.getValue());
			Integer gdt = Integer.parseInt(PlatformTypeEnum.GDT.getValue());
			// [减少对mysql的IO消耗，全部使用全广告ID集合查询]  list ===> totalList
			Map<Integer, List<AdAccountWarningResult>> warningResultMap = list.stream().collect(Collectors.groupingBy(AdAccountWarningResult::getMediaType));
			//头条广告账户ID集合 AdAccount
			List<String> ttAdIds = Lists.newArrayList();
			if (CollectionUtils.isNotEmpty(warningResultMap.get(tt))) {
				ttAdIds = warningResultMap.get(tt).stream().map(AdAccountWarningResult::getAdvertiserId).filter(Objects::nonNull).collect(Collectors.toList());
			}
			//广点通广告账户ID集合
			List<String> gdtAdIds = Lists.newArrayList();
			if (CollectionUtils.isNotEmpty(warningResultMap.get(gdt))) {
				gdtAdIds = warningResultMap.get(gdt).stream().map(AdAccountWarningResult::getAdvertiserId).filter(Objects::nonNull).collect(Collectors.toList());
			}
			//当前页-获取总余额- [减少对mysql的IO消耗，全部使用全广告ID集合查询]全部账户总余额
			List<Advertising> ttAdList = this.getTtAdAccountListByIds(ttAdIds);
			List<GdtAdvFunds> gdtAdList = this.getGdtAdAccountListByIds(gdtAdIds);

			//获取累计总余额
			BigDecimal sumTtBalance = ttAdList.stream().map(item -> item.getBalance()).reduce(BigDecimal.ZERO, BigDecimal::add);
			BigDecimal sumGdtBalance = gdtAdList.stream().map(item -> item.getTotalBalance()).reduce(BigDecimal.ZERO, BigDecimal::add);
			totalBalance = sumTtBalance.add(sumGdtBalance);

			list.forEach(warningResultVo -> {
				if (CollectionUtils.isNotEmpty(adAccountList)) {
					this.setSysUserName(adAccountList);
					//设置广告账户名称、投放人
					adAccountList.forEach(accountVo -> {
						if (accountVo.getAdvertiserId().equals(warningResultVo.getAdvertiserId())) {
							warningResultVo.setAdvertiserName(accountVo.getAdvertiserName());
							warningResultVo.setThrowUser(accountVo.getThrowUserName());
						}
					});
				}
				//设置余额
				if (CollectionUtils.isNotEmpty(ttAdList)) {
					ttAdList.forEach(ttAd -> {
						if (warningResultVo.getAdvertiserId().equals(ttAd.getAdvertiserId())) {
							warningResultVo.setBalance(ttAd.getBalance());
							// 现金可用余额 --划款用
							warningResultVo.setCashBalance(ttAd.getValidCash());
							// 赠款可用余额 --划款用
							warningResultVo.setGrantBalance(ttAd.getValidGrant());
						}
					});
				}
				if (CollectionUtils.isNotEmpty(gdtAdList)) {
					gdtAdList.forEach(gdtAd -> {
						if (warningResultVo.getAdvertiserId().equals(gdtAd.getAccountId())) {
							warningResultVo.setBalance(gdtAd.getTotalBalance());
						}
					});
				}
			});
		}
		return totalBalance;
	}

	@Override
	public R refund(Integer mediaType, String advertiserId) {
		Integer tt = Integer.parseInt(PlatformTypeEnum.TT.getValue());
		Integer gdt = Integer.parseInt(PlatformTypeEnum.GDT.getValue());
		List<String> ids = Lists.newArrayList(advertiserId);
		List<String> errorMsg = Lists.newArrayList();
		if (tt.equals(mediaType)) {
			List<Advertising> ttAdList = this.getTtAdAccountListByIds(ids);
			if (CollectionUtils.isEmpty(ttAdList)) {
				return R.failed("广告账户不存在[" + advertiserId + "]");
			}
			Advertising ad = ttAdList.get(0);
			if (ad.getBalance().compareTo(BigDecimal.ZERO) == 0) {
				return R.failed("广告账户总余额为0,不能退款[" + advertiserId + "]");
			}

			R r = this.getAdAgentId(advertiserId, mediaType);
			if (CommonConstants.FAIL.equals(r.getCode())) {
				return r;
			}
			Long adAgentId = (Long) r.getData();
			//退现金 CASH：现金  退赠款 GRANT：赠款
			if (ad.getValidCash().compareTo(BigDecimal.ZERO) == 1) {
				ResponseBean responseBean = this.sendHttpTt4Refund(advertiserId, adAgentId, "CASH", ad.getCash().longValue());
				if (responseBean != null && !"0".equals(responseBean.getCode())) {
					if ("40700".equals(responseBean.getCode())) {
						errorMsg.add("有效现金余额不足");
					}
				}
			}
			if (ad.getValidGrant().compareTo(BigDecimal.ZERO) == 1) {
				ResponseBean responseBean = this.sendHttpTt4Refund(advertiserId, adAgentId, "GRANT", ad.getGrant().longValue());
				if (responseBean != null && !"0".equals(responseBean.getCode())) {
					if ("40700".equals(responseBean.getCode())) {
						errorMsg.add("有效赠款余额不足");
					}
				}
			}
		} else if (gdt.equals(mediaType)) {
			List<GdtAdvFunds> gdtAdList = this.getGdtAdAccountListByIds(ids);
			if (CollectionUtils.isEmpty(gdtAdList)) {
				return R.failed("广告账户不存在[" + advertiserId + "]");
			}
			GdtAdvFunds ad = gdtAdList.get(0);
			if (ad.getTotalBalance().compareTo(BigDecimal.ZERO) == 0) {
				return R.failed("广告账户总余额为0,不能退款[" + advertiserId + "]");
			}
			R r = this.getAdAgentId(advertiserId, mediaType);
			if (CommonConstants.FAIL.equals(r.getCode())) {
				return r;
			}
			Long adAgentId = (Long) r.getData();
			List<GdtAdvFundsVO> fundList = ad.getFundList();
			if (CollectionUtils.isNotEmpty(fundList)) {
				fundList.forEach(gdtAdvFundsVO -> {
					// FUND_STATUS_NORMAL - 有效
					// FUND_STATUS_NOT_ENOUGH - 余额不足
					// FUND_STATUS_CLOSED - 资金账户已销户
					// FUND_STATUS_FROZEN - 资金冻结
					// 有余额并且资金状态为有效才能退款
					if (gdtAdvFundsVO.getBalance().compareTo(BigDecimal.ZERO) == 1
							&& "FUND_STATUS_NORMAL".equals(gdtAdvFundsVO.getFund_status())) {
						ResponseBean responseBean = this.sendHttpGdt4Refund(advertiserId, adAgentId, gdtAdvFundsVO);
						if (responseBean != null && !"0".equals(responseBean.getCode())) {
							errorMsg.add(responseBean.getMessage());
						}
					}
//					else {
//						errorMsg.add("["+gdtAdvFundsVO.getFund_type()+"]余额不足或资金状态非有效状态");
//					}
				});
			}
		}
		if (CollectionUtils.isEmpty(errorMsg)) {
			return R.ok();
		} else {
			return R.failed(JSON.toJSONString(errorMsg));
		}
	}

	private R getAdAgentId(String advertiserId, Integer mediaType) {
		//获取当前时间内的代理商
		AdTtTransferDto atoIn = new AdTtTransferDto();
		atoIn.setAdvertiserId(Long.valueOf(advertiserId));
		AdTtTransferVo agentVo = adTtTransferMapper.queryAgentList(atoIn);
		if (agentVo == null) {
			return R.failed("广告账户没有设置代理商,不能退款[" + advertiserId + "]");
		}
		//获取代理商对应渠道绑定的代理商ID
		AdAgentTransfer adAgentTransfer = adAgentTransferMapper.selectOne(Wrappers.<AdAgentTransfer>lambdaQuery()
				.eq(AdAgentTransfer::getAgentId, agentVo.getAgentId())
				.eq(AdAgentTransfer::getPlatform, mediaType));
		if (adAgentTransfer == null || adAgentTransfer.getAdagentId() == null) {
			return R.failed("广告账户所属代理商没有设置代理商ID,不能退款[" + advertiserId + "]");
		}
		Long adAgentId = adAgentTransfer.getAdagentId();
		return R.ok(adAgentId);
	}

	private ResponseBean sendHttpTt4Refund(String advertiserId, Long agentId, String transferType, Long amount) {
		String accessToken = ttAccesstokenService.fetchAccesstoken(advertiserId);
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("advertiser_id", advertiserId);
		data.put("agent_id", agentId);
		data.put("transfer_type", transferType);
		data.put("amount", amount);
		String resultStr = OEHttpUtils.doPost("https://ad.oceanengine.com/open_api/2/agent/advertiser/refund/", data, accessToken);
		log.info("头条广告主账户将款项退回至代理商账户==>resultStr:{}", resultStr);
		return JSON.parseObject(resultStr, ResponseBean.class);
	}

	private ResponseBean sendHttpGdt4Refund(String advertiserId, Long agentId, GdtAdvFundsVO gdtAdvFundsVO) {
		ResponseBean responseBean = new ResponseBean();
		Map<String, String> paramMap = gdtAccesstokenService.fetchAccesstoken(advertiserId);
		if (paramMap == null || StringUtils.isEmpty(paramMap.get("access_token"))) {
			responseBean.setCode("10001");
			responseBean.setMessage("广点通授权失效");
			return responseBean;
		}
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("account_id", advertiserId);
		data.put("fund_type", gdtAdvFundsVO.getFund_type());
		data.put("amount", gdtAdvFundsVO.getBalance().intValue());
		// 当值为 ADVERTISER_TO_AGENCY 时代表子客户转账给代理商
		data.put("transfer_type", "ADVERTISER_TO_AGENCY");
		String result = OEHttpUtils.doPost(gdtUrl + "fund_transfer/add" + "?" + MapUtils.queryString(paramMap), data);
		log.info("广点通广告主账户将款项退回至代理商账户==>resultStr:{}", result);
		return JSON.parseObject(result, ResponseBean.class);
	}

	private void setSysUserName(List<AdAccount> list) {
		List<String> userIds = list.stream().map(AdAccount::getThrowUser).filter(v -> StringUtils.isNotBlank(v)).collect(Collectors.toList());
		List<Integer> ids = userIds.stream().distinct().map(v -> Integer.parseInt(v)).collect(Collectors.toList());
		R<List<SysUser>> userList = remoteUserService.getUserListByUserIds(SecurityConstants.FROM_IN, ids);
		if (userList != null && CollectionUtils.isNotEmpty(userList.getData())) {
			//Map<用户ID,用户名称>
			Map<Integer, String> userMap = userList.getData().stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getRealName));
			list.forEach((item) -> {
				//未关联投放人
				if (StringUtils.isBlank(item.getThrowUser())) {
					item.setThrowUserName("未关联投放人");
				} else {
					if (CollectionUtils.isNotEmpty(userMap)) {
						item.setThrowUserName(userMap.get(Integer.parseInt(item.getThrowUser())));
					}
				}
			});
		}
	}

	private List<String> getEmailAddressList(List<Integer> userIds) {
		List<String> result = Lists.newArrayList();
		//List<Integer> ids = userIds.stream().distinct().map(v -> Integer.parseInt(v)).collect(Collectors.toList());
		R<List<SysUser>> userList = remoteUserService.getUserListByUserIds(SecurityConstants.FROM_IN, userIds);
		if (userList != null && CollectionUtils.isNotEmpty(userList.getData())) {
			//过滤邮箱为空的用户
			result = userList.getData().stream().map(SysUser::getEmail).filter(Objects::nonNull).collect(Collectors.toList());
		}
		return result;
	}

	private String getEmailContent(List<AdAccountWarningResult> totalList) {
		// 不活跃账号总数
		int advertiserCount = totalList.size();
		//按总余额降序后取前20输出到邮件
		totalList = totalList.stream().sorted(Comparator.comparing(AdAccountWarningResult::getBalance).reversed()).collect(Collectors.toList());
		List<AdAccountWarningResult> top20 = totalList.stream().limit(20).collect(Collectors.toList());
		String des = "<span style='font-weight: bold;'>" + "当前不活跃账号总数：" + advertiserCount + "</span><br/>"
				+ "<span style='font-weight: bold;'> 列表如下(前20条)：</span><br/>";
		String head = "<table style=\"color:#333333;border-width: 1px;border-color: #666666;border-collapse: collapse;\">\n" +
				"    <tr>\n" +
				"    <th style=\"border-width: 1px;border-style: solid;background-color: #C5D9F1;padding: 8px;border-color: #666666;\">\n" +
				"        媒体\n" +
				"    </th>\n" +
				"    <th style=\"border-width: 1px;border-style: solid;background-color: #C5D9F1;padding: 8px;border-color: #666666;\">\n" +
				"        广告账户名称\n" +
				"    </th>\n" +
				"    <th style=\"border-width: 1px;border-style: solid;background-color: #C5D9F1;padding: 8px;border-color: #666666;\">\n" +
				"        广告账户ID\n" +
				"    </th>\n" +
				"    <th style=\"border-width: 1px;border-style: solid;background-color: #C5D9F1;padding: 8px;border-color: #666666;\">\n" +
				"        余额\n" +
				"    </th>\n" +
				"    <th style=\"border-width: 1px;border-style: solid;background-color: #C5D9F1;padding: 8px;border-color: #666666;\">\n" +
				"        投放人\n" +
				"    </th>\n" +
				"    </tr>";

		String data = "";
		for (AdAccountWarningResult warningResult : top20) {
			String mediaName = "头条";
			if (warningResult.getMediaType().equals(Integer.parseInt(PlatformTypeEnum.GDT.getValue()))) {
				mediaName = "广点通";
			}
			String advertiserId = warningResult.getAdvertiserId();
			String advertiserName = warningResult.getAdvertiserName();
			String balance = warningResult.getBalance().toString();
			String throwUser = warningResult.getThrowUser();
			data += "<tr>\n" +
					"        <td style=\"border-width: 1px;border-style: solid;background-color: #ffffff;padding: 8px;border-color: #666666;\">" + mediaName + "</td>\n" +
					"        <td style=\"text-align: center;border-width: 1px;border-style: solid;background-color: #ffffff;padding: 8px;border-color: #666666;\">" + advertiserName + "</td>\n" +
					"        <td style=\"text-align: center;border-width: 1px;border-style: solid;background-color: #ffffff;padding: 8px;border-color: #666666;\">" + advertiserId + "</td>\n" +
					"        <td style=\"text-align: center;border-width: 1px;border-style: solid;background-color: #ffffff;padding: 8px;border-color: #666666;\">" + balance + "</td>\n" +
					"        <td style=\"text-align: center;border-width: 1px;border-style: solid;background-color: #ffffff;padding: 8px;border-color: #666666;\">" + throwUser + "</td>\n" +
					"    </tr>";

		}
		String endTable = "</table>";
		String content = des + head + data + endTable;
		return content;
	}

	/**
	 * @param userId              用户ID 定时器执行时为-1
	 * @param activeList          头条或广点通账户表总余额大于0的账户ID集合
	 * @param adAccountWarnVoList clickhouse 活跃账户List
	 * @param type                渠道类型
	 * @return
	 */
	private List<AdAccountWarningResult> dealNoActiveAccount(Integer userId, List<String> activeList, List<AdAccountWarnVo> adAccountWarnVoList, Integer type) {
		List<AdAccountWarningResult> noActiveList = Lists.newArrayList();
		if (CollectionUtils.isNotEmpty(activeList)) {
			if (CollectionUtils.isNotEmpty(adAccountWarnVoList)) {
				Map<Integer, List<AdAccountWarnVo>> chActiveMap = adAccountWarnVoList.stream().collect(Collectors.groupingBy(AdAccountWarnVo::getMediaType));
				//可能没有某个类型的活跃账号
				if (CollectionUtils.isNotEmpty(chActiveMap.get(type))) {
					List<String> chActiveList = chActiveMap.get(type).stream().map(AdAccountWarnVo::getAdAccount).collect(Collectors.toList());
					// ttAdvertisingList -  adAccountWarnVoList 表示：有余额且没有消耗-直接设为不活跃,广点通同理
					if (CollectionUtils.isNotEmpty(chActiveList)) {
						activeList = activeList.stream().filter(v -> !chActiveList.contains(v)).collect(Collectors.toList());
					}
				}
			}
			activeList.forEach(advertiserId -> {
				AdAccountWarningResult gdtResult = new AdAccountWarningResult();
				gdtResult.setMediaType(type);
				gdtResult.setAdvertiserId(advertiserId);
				gdtResult.setActive(2);//1活跃 2不活跃
				//这样的账号默认不活跃 最后活跃时间 is null
				gdtResult.setCreateId(Long.valueOf(userId));
				gdtResult.setUpdateId(Long.valueOf(userId));
				noActiveList.add(gdtResult);
			});
		}
		return noActiveList;
	}
}
